<?php

class stg_Universe
{
	protected $__permissions = array(

	);
	protected $_name;
	protected $_rules = array(); // of Rule
	protected $_objects_by_id = array(); // of (int, Object)
	protected $_objects_by_name = array(); // of Object
	protected $_players = array(); // of Player
	protected $_last_ID = 0;

	function __construct($name)
	{
		e("Building universe $name");
		$this->name = $name;
	}

	function add_rule($rule)
	{
		array_push($this->rules, $rule);
	}

	function add_player($player)
	{   
		$this->add_object($player);		
		$this->players[$player->name] = $player;
	}

	function add_object($object)
	{
		if (array_key_exists($object->name, $this->objects)) {
			throw new Exception("There is already an object named {$object->name} in universe {$this->name}");
		}
		if ($object->universe) {
			throw new Exception("The object {$object->name} is already associated with universe {$this->name}");
		}
		$this->objects[$object->name] = $object;
		$object->universe = $this;
		$object->ID = $this->create_ID();
		
		e("Added {$object->complete_name} with ID #{$object->ID}");
		
		return $object->ID;
	}

	function create_ID() {
		$this->last_ID++;
		return $this->last_ID;
	}
	//* Server movement
	function movement()
	{
		return array();
	}

	static function order_compare($a, $b)
	{
		return 0;
	}

	function assign_scores()
	{
	}

	function is_finished()
	{
		return false;
	}

	function known_universe_for($player)
	{
		return clone $this;
	}

	function& __get($name)
	{
		// Try first with the method get_$name
		if (method_exists($this, "get_$name"))
		{
			$result = call_user_func(array(&$this, "get_$name"));
			return $result;
		}
		// Second with the attribute _$name
		elseif (property_exists($this, "_$name"))
		{
			return $this->{"_$name"};
		}
		// The property is not properly defined!
		else
		{
			throw new Exception("Property $name does not exist in class ".get_class($this)."!!");
		}
	}

	function __set($name, $val)
	{
		if (method_exists($this, "set_$name"))
		{
			call_user_func(array(&$this, "set_$name"), $val);
		}
		elseif (property_exists($this, "_$name"))
		{
			$caller_class = get_caller_class();
			$caller_object = get_caller_object();
			if (property_exists($this, '__permissions'))
			{
				$perms = $this->__permissions;
			}
			else
			{
				$perms = array();
			}
			if  (
			    get_class($this) == $caller_class ||
				is_subclass_of($this, $caller_class) ||
			    is_writable_by($caller_object, $perms, $name)
				)
			{
					$this->{"_$name"} = $val;
			}
			else
			{
				throw new Exception("Property $name in class ".get_class($this)." is not writable by ".get_caller_class()." instances");
			}
		}
		// The property is not properly defined!
		else
		{
			throw new Exception("Property $name does not exist in class ".get_class($this)."!!");
		}
	}

}

?>
